﻿#include "YMuxer.h"

extern "C"
{
#include "libavformat/avformat.h"
}
/// <summary>
	/// 打开封装器
	/// </summary>
	/// <param name="url">输出路径</param>
	/// <returns></returns>
//AVFormatContext* YMuxer::Open(const char* url)
//{
//	std::unique_lock<std::mutex> lock(mutex);
//	AVFormatContext* oc = nullptr;
//	//创建上下文
//	auto re = avformat_alloc_output_context2(&oc, NULL, NULL, url);
//	PrintError(re, "avformat_alloc_output_context2");
//
//	//添加视频音频流
//	auto vs = avformat_new_stream(oc, NULL);   //视频流
//	vs->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
//	this->vs_ = vs;
//	auto as = avformat_new_stream(oc, NULL);   //音频流
//	as->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
//	this->as_ = as;
//
//
//	//打开IO
//	re = avio_open(&oc->pb, url, AVIO_FLAG_WRITE);
//	PrintError(re, "avio_open");
//	return oc;
//}

//// 打开封装
AVFormatContext* YMuxer::Open(const char* url,
	AVCodecParameters* video_para,
	AVCodecParameters* audio_para)
{
	std::unique_lock<std::mutex> lock(mutex);
	AVFormatContext* c = nullptr;
	//创建上下文
	auto re = avformat_alloc_output_context2(&c, NULL, NULL, url);
	PrintError(re, "avformat_alloc_output_context2");

	//添加视频音频流
	if (video_para)
	{
		auto vs = avformat_new_stream(c, NULL);   //视频流
		avcodec_parameters_copy(vs->codecpar, video_para);
		vs_ = vs;
	}
	if (audio_para)
	{
		auto as = avformat_new_stream(c, NULL);   //音频流
		avcodec_parameters_copy(as->codecpar, audio_para);
		as_ = as;
	}

	//打开IO
	re = avio_open(&c->pb, url, AVIO_FLAG_WRITE);
	PrintError(re, "avio_open");
	av_dump_format(c, 0, url, 1);
	return c;
}

/// <summary>
/// 写入头部信息
/// </summary>
/// <returns></returns>
bool YMuxer::WriteHead()
{
	std::unique_lock<std::mutex> lock(mutex);
	if (!c_context)return false;
	auto re = avformat_write_header(c_context, nullptr);
	PrintError(re, "avformat_write_header");
	return true;
}

/// <summary>
/// 写入AVPacket
/// </summary>
/// <param name="pkt"></param>
/// <returns></returns>
bool YMuxer::Write(AVPacket* pkt)
{
	std::unique_lock<std::mutex> lock(mutex);
	if (!c_context)return false;
	//写入一帧数据，内部缓冲排序dts，通过pkt=null 可以写入缓冲
	auto re = av_interleaved_write_frame(c_context, pkt);
	if (re != 0)
	{
		PrintError(re, "av_interleaved_write_frame");
	}
	
	return true;
}
/// <summary>
/// 写入尾部信息
/// </summary>
/// <returns></returns>
bool YMuxer::WriteEnd()
{
	std::unique_lock<std::mutex> lock(mutex);
	if (!c_context)return false;
	av_interleaved_write_frame(c_context, nullptr);//写入排序缓冲
	auto re = av_write_trailer(c_context);
	if (re != 0)
	{
		PrintError(re, "av_write_trailer");
	}
	return true;
}

void YMuxer::set_src_video_time_base(AVRational* tb)
{
	if (!tb)return;
	std::unique_lock<std::mutex> lock(mutex);
	if (!src_video_time_base_)
		src_video_time_base_ = new AVRational();
	*src_video_time_base_ = *tb;
}
void YMuxer::set_src_audio_time_base(AVRational* tb)
{
	if (!tb)return;
	std::unique_lock<std::mutex> lock(mutex);
	if (!src_audio_time_base_)
		src_audio_time_base_ = new AVRational();
	*src_audio_time_base_ = *tb;
}


YMuxer::YMuxer()
{
}

YMuxer::~YMuxer()
{
}
